package com.googlecode.intellimars.sabotter.ui;

import com.googlecode.intellimars.sabotter.SabotterConfig;
import com.googlecode.intellimars.sabotter.SabotterPlugin;
import com.googlecode.intellimars.sabotter.TimeLineWrapper;
import com.googlecode.intellimars.sabotter.action.RefreshViewAction;
import com.googlecode.intellimars.sabotter.action.SignOutAction;
import com.googlecode.intellimars.sabotter.action.UpdateStatusAction;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.SearchTextField;
import com.intellij.ui.EnumComboBoxModel;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.DefaultEditorKit.CopyAction;
import javax.swing.text.Document;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.StyleSheet;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class SabotterWindow {
    private static final Logger LOG = Logger.getInstance("sabotter");

    public JPanel rootPanel;

    private JTextField usernameField;
    private JPasswordField passwordField;
    private JButton signinButton;

    private JTextField serverUrlField;
    private JCheckBox autoSigninCheckBox;
    private JComboBox intervalField;
    private JSpinner fontSizeField;

    private JEditorPane friendTimelinePane;
    private JEditorPane repliesTimelinePane;
    private JEditorPane directMessagePane;

    private HyperlinkLabel hyperlinkLabel;
    private JPanel toolbarPane;
    private JComboBox fontFamilyField;
    private JPanel userFilterPane;
    private SearchTextField userFilterField;
    private JCheckBox useProxyCheckBox;

    private final CardLayout layoutManager;
    private final SabotterPlugin sabotterPlugin;

    private String filterToken = "";

    public SabotterWindow(SabotterPlugin parent) {
        layoutManager = (CardLayout) rootPanel.getLayout();
        layoutManager.show(rootPanel, "setting");
        sabotterPlugin = parent;

        JPopupMenu popupMenu = new JPopupMenu();
        popupMenu.add(new CopyAction());
        friendTimelinePane.setComponentPopupMenu(popupMenu);
        repliesTimelinePane.setComponentPopupMenu(popupMenu);
        directMessagePane.setComponentPopupMenu(popupMenu);
        friendTimelinePane.addHyperlinkListener(new SabotterHyperlinkListener());
        repliesTimelinePane.addHyperlinkListener(new SabotterHyperlinkListener());
        // TODO:ダイレクトメッセージってどう表示させようかな...
        directMessagePane.setText("<b>Not Implemented</b>");

        signinButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                activate();
            }
        });
        userFilterField.addDocumentListener(new DocumentAdapter() {
            protected void textChanged(DocumentEvent e) {
                int length = e.getDocument().getLength();
                System.out.println("length = " + length);
                if (length == 0 || length > 1) {
                    // 空っぽか２文字以上入力したらタイムラインを更新する
                    filterToken = userFilterField.getText().trim();
                    _updateTimeline();
                }
            }
        });
        userFilterField.addKeyboardListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                // ENTERキーを押したら，履歴に追加する
                if (e.getKeyCode() == KeyEvent.VK_ENTER) userFilterField.addCurrentTextToHistory();
            }
        });
    }


    private void setStyle(HTMLDocument doc) {
        StyleSheet styleSheet = doc.getStyleSheet();
        Style body = styleSheet.getStyleSheets()[0].getStyle("body");
        if (body != null) {
            body.addAttribute(StyleConstants.FontFamily, sabotterPlugin.config.getFontFamily());
            String fontSize = String.valueOf(sabotterPlugin.config.getFontSize() + "pt");
            body.addAttribute(StyleConstants.FontSize, fontSize);
        }
    }

    private void activate() {
        getData(sabotterPlugin.config);
        if (sabotterPlugin.signIn()) {
            setStyle((HTMLDocument) friendTimelinePane.getDocument());
            setStyle((HTMLDocument) repliesTimelinePane.getDocument());
            setStyle((HTMLDocument) directMessagePane.getDocument());
            layoutManager.show(rootPanel, "main");
        }
    }

    public void deactivate() {
        clearDocument();
        layoutManager.show(rootPanel, "setting");
    }


    public void setData(SabotterConfig data) {
        LOG.info("setdata:" + data);
        usernameField.setText(data.getUsername());
        passwordField.setText(data.getPassword());
        serverUrlField.setText(data.getServerUrl());
        switch (data.getInterval()) {
            case 0 : intervalField.setSelectedItem(IntervalEnum.None); break;
            case 10 : intervalField.setSelectedItem(IntervalEnum.a10sec); break;
            case 180: intervalField.setSelectedItem(IntervalEnum.a3min); break;
            case 300: intervalField.setSelectedItem(IntervalEnum.a5min); break;
            default:  intervalField.setSelectedItem(IntervalEnum.a1min);
        }
        autoSigninCheckBox.setSelected(data.isAutoSignin());
        useProxyCheckBox.setSelected(data.isUseProxy());
        fontFamilyField.setSelectedItem(data.getFontFamily());
        fontSizeField.setValue(data.getFontSize());
        
        // へんぴなところにオートログインを仕込んでいる。:-)
        if (data.isAutoSignin()) activate();
    }

    public void getData(SabotterConfig data) {
        data.setUsername(usernameField.getText());
        data.setPassword(String.valueOf(passwordField.getPassword()));
        data.setServerUrl(serverUrlField.getText());
        data.setInterval(((IntervalEnum)intervalField.getSelectedItem()).value);
        data.setAutoSignin(autoSigninCheckBox.isSelected());
        data.setUseProxy(useProxyCheckBox.isSelected());
        data.setFontFamily((String)fontFamilyField.getSelectedItem());
        data.setFontSize((Integer)fontSizeField.getValue());
    }

    public void updateTimeLine() {
        toolbarPane.setEnabled(false);
        if (sabotterPlugin.timeLine.hasNewMessage()) {
            _updateTimeline();
        }
        toolbarPane.setEnabled(true);
    }

    private synchronized void _updateTimeline() {
        TimeLineWrapper timeline = sabotterPlugin.timeLine;
        clearDocument(friendTimelinePane);
        clearDocument(repliesTimelinePane);
        friendTimelinePane.setText(timeline.getFriendsTimelineContents(filterToken));
        repliesTimelinePane.setText(timeline.getRepliesTimelineContents(filterToken));
    }

    private void clearDocument() {
        clearDocument(friendTimelinePane);
        clearDocument(repliesTimelinePane);
    }
    private void clearDocument(JEditorPane editorPane) {
        editorPane.setText("");
        editorPane.getDocument().putProperty(Document.StreamDescriptionProperty, null);
    }

    private void createUIComponents() {
        DefaultActionGroup toolbarActions = new DefaultActionGroup();
        toolbarActions.add(new SignOutAction());
        toolbarActions.add(new RefreshViewAction());
        toolbarActions.add(new UpdateStatusAction());
        toolbarPane = new JPanel(new BorderLayout());
        toolbarPane.add(ActionManager.getInstance()
                                     .createActionToolbar("toolbar", toolbarActions, true).getComponent(), BorderLayout.CENTER);

        hyperlinkLabel = new HyperlinkLabel("twitter");
        hyperlinkLabel.addHyperlinkListener(new HyperlinkListener() {
            public void hyperlinkUpdate(HyperlinkEvent e) {
                BrowserUtil.launchBrowser("http://twitter.com/home");
            }
        });

        intervalField = new ComboBox();
        intervalField.setModel(new EnumComboBoxModel<IntervalEnum>(IntervalEnum.class));
        fontSizeField = new JSpinner(new SpinnerNumberModel(10, 8, 16, 1));

        userFilterField = new SearchTextField();
    }

    private class SabotterHyperlinkListener implements HyperlinkListener {
        public void hyperlinkUpdate(HyperlinkEvent e) {
            if (!EventType.ACTIVATED.equals(e.getEventType())) return;

            if (!e.getURL().getHost().startsWith("sabotter")) {
                BrowserUtil.launchBrowser(e.getURL().toString());
            }
            if (e.getURL().getFile().startsWith("/reply")) {
                final String id = e.getURL().getQuery().replaceAll("id=", "");
                LOG.info(id);
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        new SabotterPostDialog(sabotterPlugin.project, id);
                    }
                });
            }
        }
    }

    private static enum IntervalEnum {
        None   (0, "None"),
        a10sec (10, "10sec"),
        a1min  (60, "1min"),
        a3min  (180, "3min"),
        a5min  (300, "5min");

        public int value;
        private String descripton;

        IntervalEnum(int v, String s) {
            value = v;
            descripton = s;
        }
        public String toString() {
            return descripton;
        }
    }
}
